package com.thyc.server;


import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.thyc.entity.Distribution;
import com.thyc.entity.SmsInfo;
import com.thyc.entity.SourceData;
import com.thyc.entity.WarningContacts;
import com.thyc.enums.EquipmentEnum;
import com.thyc.service.DistributionService;
import com.thyc.service.SmsInfoService;
import com.thyc.service.SourceDataService;
import com.thyc.service.WarningContactsService;
import com.thyc.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class ParseData {

    private static final String CHANNEL_LIST = "CHANNEL_LIST";

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private SourceDataService sourceDataService;

    @Resource
    private DistributionService distributionService;

    @Resource
    private WarningContactsService warningContactsService;

    @Resource
    private SmsInfoService smsInfoService;

    @Resource
    private SendInfo sendInfo;

    public void parseData(List<Integer> dataList) {
        List<BigDecimal> sourceDataList = new ArrayList<>();
        for (int i = 0; i < dataList.size(); i += 2) {
            Integer Ln = dataList.get(i);
            Integer Hn = dataList.get(i + 1);
            Integer Xn = Hn * 256 + Ln;
            //采集模块输出电压公式  Um = ( X / 65536 ) * 5 - 2.5
            BigDecimal Um = new BigDecimal(Xn)
                    .divide(new BigDecimal(65536))
                    .multiply(new BigDecimal(5)).setScale(6, RoundingMode.HALF_DOWN)
                    .subtract(new BigDecimal(2.5));

            //电压采集公式 Ug = Um / W   放大倍数建议设置 100
            BigDecimal Ug = Um.divide(new BigDecimal(100)).setScale(6, RoundingMode.HALF_DOWN);

            //速度值转换 V=Ug*25000/0.3   v：速度mm/s   Ug：电压V
            BigDecimal V = Ug.multiply(new BigDecimal("25000")).divide(new BigDecimal("0.3"),6,RoundingMode.HALF_DOWN);

            //这个是加速度值的转换 已弃用
            //加速度值转换 g=B/K*Ug   单位（m/s2）
            //默认 K=900 灵敏度，单位：pC/ms-2, B=2200 反馈电容，单位 pF
//            BigDecimal divide = new BigDecimal(2200).divide(new BigDecimal(900), RoundingMode.HALF_DOWN);
//            BigDecimal g = divide.multiply(Ug).setScale(6, RoundingMode.HALF_DOWN);
            sourceDataList.add(V);
        }
        List<String> channelList = (List<String>) redisUtil.get(CHANNEL_LIST);
        List<SourceData> sourceData = new ArrayList<>();
        Date date = new Date();
        channelList.forEach(channel -> {
            SourceData sd = new SourceData()
                    .setAddTime(date)
                    .setDataOne(sourceDataList.get(0))
                    .setUnitOne("mm/s")
                    .setModelNum("4103729")
                    .setPassageway(channel)
                    .setSensorModel(EquipmentEnum.getByChannel(channel).getSensorModel())
                    .setSensorNum(EquipmentEnum.getByChannel(channel).getSensorNumber());
            sourceData.add(sd);
            sd.setId(new Date().getTime());
            redisUtil.set(channel + RandomUtil.randomString(6), sd, 3);
            //检查报警值
            checkData(channel,sourceDataList.get(0).doubleValue());
            sourceDataList.remove(0);
        });
        storeData(sourceData);
    }

    @Async
    void storeData(List<SourceData> sourceData) {
        sourceDataService.saveBatch(sourceData);
    }

    @Async
    void checkData(String channelNum,Double warningValue) {
        Distribution one = distributionService.getOne(new LambdaQueryWrapper<Distribution>().eq(Distribution::getChannelNumber, channelNum));
        if (null != one) {
            //如果实时返回的值小于0 去对比负数组
            if (CompareUtil.compare(warningValue, 0d) < 0) {
                //-------------------------------------负数值-------------------------------------
                //预警值1取两位有效值之后转double
                double negativeYjz = one.getNegativeWarningValue().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                //预警值2取两位有效值之后转double
                double negativeYjzt = one.getNegativeWarningValueTwo().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                //报警值取两位有效值之后转double
                double negativeBjz = one.getNegativeThreshold().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                //1.如果返回值比报警值负值还小 则直接报警并且添加告警信息到数据库
                if (warningValue < negativeBjz) {
                    //添加记录到数据库
                    List<WarningContacts> list = warningContactsService.list(new LambdaQueryWrapper<WarningContacts>().eq(WarningContacts::getEnableIs, 0));
                    List<SmsInfo> smsInfos = new ArrayList<>();
                    if (list.size() != 0) {
                        list.forEach(warningContacts -> {
                            SmsInfo smsInfo = new SmsInfo();
//                            smsInfo.setInfoContent("尊敬的管理员" + warningContacts.getContactsName() + ",您监测的设备数据存在异常，时间：" + DateUtil.now() + ",请核实及时处理。");
                            smsInfo.setInfoContent("设备【18200148】数据发现异常，通道号【" + channelNum + "】，测点数据已突破报警值负值，时间：" + DateUtil.now() + ",请核实及时处理。");
                            smsInfo.setAddress(one.getRemarks());
                            smsInfo.setModelNum("18200148");
                            smsInfo.setSensorModel("4103517");
                            smsInfo.setSensorNum(one.getNumber());
                            smsInfo.setChannelNumber(channelNum);
                            smsInfo.setWarningValue(warningValue);
                            smsInfo.setInfoType(1);
                            smsInfo.setSendToUser(warningContacts.getContactsName());
                            smsInfo.setSendTel(warningContacts.getContactsTel());
                            smsInfos.add(smsInfo);
                        });
                        smsInfoService.saveBatch(smsInfos);
                        //发送告警信息
                        sendInfo.sendWarningInfo(list, "18200148", "4103517", one.getNumber(), warningValue);
                    }
                    return;
                }
                //1.如果返回值比二级预警值小但是大于报警值 则只保存预警信息到数据库
                if (warningValue < negativeYjzt && warningValue > negativeBjz) {
                    SmsInfo smsInfo = new SmsInfo();
                    smsInfo.setInfoContent("设备【18200148】数据发现异常，通道号【" + channelNum + "】，测点数据到达二级预警值负值，时间：" + DateUtil.now() + ",请核实及时处理。");
                    smsInfo.setAddress(one.getRemarks());
                    smsInfo.setModelNum("18200148");
                    smsInfo.setSensorModel("4103517");
                    smsInfo.setSensorNum(one.getNumber());
                    smsInfo.setChannelNumber(channelNum);
                    smsInfo.setWarningValue(warningValue);
                    smsInfo.setInfoType(3);
                    smsInfoService.save(smsInfo);
                    return;
                }
                //1.如果返回值比一级预警值小但是大于二级报警值 则只保存预警信息到数据库
                if (warningValue < negativeYjz && warningValue > negativeYjzt) {
                    SmsInfo smsInfo = new SmsInfo();
                    smsInfo.setInfoContent("设备【18200148】数据发现异常，通道号【"+channelNum+"】，测点数据到达一级预警值负值，时间：" + DateUtil.now() + ",请核实及时处理。");
                    smsInfo.setAddress(one.getRemarks());
                    smsInfo.setModelNum("18200148");
                    smsInfo.setSensorModel("4103517");
                    smsInfo.setSensorNum(one.getNumber());
                    smsInfo.setChannelNumber(channelNum);
                    smsInfo.setWarningValue(warningValue);
                    smsInfo.setInfoType(3);
                    smsInfoService.save(smsInfo);
                    return;
                }
                //如果实时返回的值大于0 去对比正数组的数据
            } else {
                //-------------------------------------正数值-------------------------------------
                //预警值1取两位有效值之后转double
                double yjz = one.getWarningValue().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                //预警值2取两位有效值之后转double
                double yjzt = one.getWarningValueTwo().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                //报警值取两位有效值之后转double
                double bjz = one.getThreshold().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                //1.如果返回值比报警值大 ，则直接报警并且添加告警信息到数据库
                if (warningValue > bjz) {
                    //添加记录到数据库
                    List<WarningContacts> list = warningContactsService.list(new LambdaQueryWrapper<WarningContacts>().eq(WarningContacts::getEnableIs, 0));
                    List<SmsInfo> smsInfos = new ArrayList<>();
                    if (list.size() != 0) {
                        list.forEach(warningContacts -> {
                            SmsInfo smsInfo = new SmsInfo();
//                            smsInfo.setInfoContent("尊敬的管理员" + warningContacts.getContactsName() + ",您监测的设备数据存在异常，时间：" + DateUtil.now() + ",请核实及时处理。");
                            smsInfo.setInfoContent("设备【18200148】数据发现异常，通道号【" + channelNum + "】，测点数据已突破报警值正值，时间：" + DateUtil.now() + ",请核实及时处理。");
                            smsInfo.setAddress(one.getRemarks());
                            smsInfo.setModelNum("18200148");
                            smsInfo.setSensorModel("4103517");
                            smsInfo.setSensorNum(one.getNumber());
                            smsInfo.setChannelNumber(channelNum);
                            smsInfo.setWarningValue(warningValue);
                            smsInfo.setInfoType(1);
                            smsInfo.setSendToUser(warningContacts.getContactsName());
                            smsInfo.setSendTel(warningContacts.getContactsTel());
                            smsInfos.add(smsInfo);
                        });
                        smsInfoService.saveBatch(smsInfos);
                        //发送告警信息
                        sendInfo.sendWarningInfo(list, "18200148", "4103517", one.getNumber(), warningValue);
                    }
                    return;
                }
                //1.如果返回值比二级预警值大但是小于报警值 则只保存预警信息到数据库
                if (warningValue > yjzt && warningValue < bjz) {
                    SmsInfo smsInfo = new SmsInfo();
                    smsInfo.setInfoContent("设备【18200148】数据发现异常，通道号【"+channelNum+"】，测点数据到达二级预警值正值，时间：" + DateUtil.now() + ",请核实及时处理。");
                    smsInfo.setAddress(one.getRemarks());
                    smsInfo.setModelNum("18200148");
                    smsInfo.setSensorModel("4103517");
                    smsInfo.setSensorNum(one.getNumber());
                    smsInfo.setChannelNumber(channelNum);
                    smsInfo.setWarningValue(warningValue);
                    smsInfo.setInfoType(3);
                    smsInfoService.save(smsInfo);
                    return;
                }
                //1.如果返回值比一级预警值小但是大于二级报警值 则只保存预警信息到数据库
                if (warningValue > yjz && warningValue < yjzt) {
                    SmsInfo smsInfo = new SmsInfo();
                    smsInfo.setInfoContent("设备【18200148】数据发现异常，通道号【"+channelNum+"】，测点数据到达一级预警值正值，时间：" + DateUtil.now() + ",请核实及时处理。");
                    smsInfo.setAddress(one.getRemarks());
                    smsInfo.setModelNum("18200148");
                    smsInfo.setSensorModel("4103517");
                    smsInfo.setSensorNum(one.getNumber());
                    smsInfo.setChannelNumber(channelNum);
                    smsInfo.setWarningValue(warningValue);
                    smsInfo.setInfoType(3);
                    smsInfoService.save(smsInfo);
                    return;
                }
            }
        }

    }

}
